今天來製作 books API 端點!
首先要先創建一個新的 app,到rest_api
中輸入:
python manage.py startapp book
建立完成後記得加入settings.py
的INSTALLED_APPS
中。books app 預計只會有 serializers, urls, views,而 book model 會加在 core app 中。再來到core/models.py
中加入:
# 其他導入
from django.conf import settings
# ...
class Book(models.Model):
"""Book object."""
user = models.ForeignKey(
settings.AUTH_USER_MODEL,
on_delete=models.CASCADE,
)
title = models.CharField(max_length=255)
description = models.TextField(blank=True)
price = models.IntegerField()
def __str__(self):
return self.title
這邊在 book model 底下創建四個欄位: user, title, description, price。ForeignKey
可使兩欄位產生連結,第一個參數為了避免 hard code,所以使用settings.AUTH_USER_MODEL
,而on_delete=models.CASCADE
表示 user 被刪除時,其創建的 book object 也會一併被刪除。最底下的__str__
函式會將 title 顯示在管理員頁面中。完成後儲存並執行 migration 創建此資料表。最後記得在admin.py
中註冊此 model。
此處 Book 繼承的是
models.Model
,與 User model 不同。
接著到 book app 中新增serializers.py
檔案並加入:
from rest_framework import serializers
from core.models import Book
class BookSerializer(serializers.ModelSerializer):
"""Serializer for books."""
class Meta:
model = Book
fields = ['id', 'title', 'price']
read_only_fields = ['id']
這邊的 serializer 同樣繼承ModelSerializer
並指定 Book 為進行序列化的 model,此外指定 id 為僅供讀取的欄位。完成後到 book/views.py 中新增:
"""
Views for the book APIs.
"""
from rest_framework import viewsets
from rest_framework.authentication import TokenAuthentication
from rest_framework.permissions import IsAuthenticated
from core.models import Book
from book import serializers
class BookViewSet(viewsets.ModelViewSet):
"""View for manage book APIs."""
serializer_class = serializers.BookSerializer
queryset = Book.objects.all()
authentication_classes = [TokenAuthentication]
permission_classes = [IsAuthenticated]
def get_queryset(self):
"""Retrieve books for authenticated user."""
return self.queryset.filter(user=self.request.user).order_by('-id')
此處繼承ModelViewSet
並指定剛剛創建的BookSerializer
為serializer_class
,預設的查詢資料為所有 book objects。此端點需要授權才能進行操作,所以記得加上之前的授權方法。下方的功能是只回傳該使用者上傳的物件。完成後創建urls.py
並加入:
"""
URL mappings for the book app.
"""
from django.urls import path, include
from rest_framework.routers import DefaultRouter
from book import views
router = DefaultRouter()
router.register('books', views.BookViewSet)
app_name = 'book'
urlpatterns = [
path('', include(router.urls)),
]
這邊使用router = DefaultRouter()
來自動創建 CRUD 所需的 urls,創建完成後註冊router.register('books', views.BookViewSet)
。最後加進 urlpatterns 中。完成後進入 rest_api/urls.py 中加入 book 中的 urls:
urlpatterns = [
# ...
path('api/book/', include('book.urls')),
]
完成後,執行伺服器的時候就可以看到所有 book API 的端點顯示在 Swagger 頁面上,像這樣:
功能的部分尚未實作完畢,因此照目前裝況去測試某些端點時會發生錯誤。明天就來把功能都做完,掰掰。